package service

import (
	"context"
	"encoding/json"
	"fmt"
	"time"
	user "user_srv/basic/proto"
	"user_srv/handler/dao"
	mobile "user_srv/handler/model"
	un "user_srv/untils"
)

// 用户服务
type Server struct {
	user.UnimplementedUserServer
}

// 发送短息验证码
func (s *Server) SendSms(_ context.Context, in *user.SendSmsReq) (*user.SendSmsResp, error) {
	err := dao.SendSms(in)
	if err != nil {
		return nil, fmt.Errorf("发送短信失败: %s", err.Error())
	}
	return &user.SendSmsResp{
		Message: "发送短信成功",
	}, nil
}

// 用户注册
func (s *Server) Register(_ context.Context, in *user.RegisterReq) (*user.RegisterResp, error) {
	register, err := dao.Register(in)
	if err != nil {
		return nil, fmt.Errorf("注册用户失败: %s", err.Error())
	}
	return &user.RegisterResp{
		UserId:  int64(register.Id),
		Message: "注册用户成功",
	}, nil
}

// 模拟QQ登录
func (s *Server) QQLogin(_ context.Context, in *user.QQLoginReq) (*user.QQLoginResp, error) {
	login, err := dao.QQLogin(in)
	if err != nil {
		return nil, fmt.Errorf("QQ登录失败", err.Error())
	}
	token, err := un.JWTGenerate(login.Id)
	if err != nil {
		return nil, fmt.Errorf("生成token失败", err.Error())
	}
	return &user.QQLoginResp{
		Uid:         int64(login.Id),
		Nickname:    login.Nickname,
		Avatar:      login.Avatar,
		AccessToken: token,
	}, nil
}

// 更新用户信息或完善
func (s *Server) UpdateUserInfo(_ context.Context, in *user.UpdateUserInfoReq) (*user.UpdateUserInfoResp, error) {
	info, err := dao.UpdateUserInfo(in)
	if err != nil {
		return nil, fmt.Errorf("更新用户信息失败:%s", err.Error())
	}
	return &user.UpdateUserInfoResp{
		UserId:  int64(info.Id),
		Message: "更新用户信息成功",
	}, nil
}

// 用户上传图片
func (s *Server) UpLoadPhoto(_ context.Context, in *user.UpLoadPhotoReq) (*user.UpLoadPhotoResp, error) {
	info, err := dao.UpLoadPhoto(in)
	if err != nil {
		return nil, fmt.Errorf("更新用户信息失败:%s", err.Error())
	}
	return &user.UpLoadPhotoResp{
		PhotoId: int64(info.Id),
	}, nil
}

// 用户购买会员套餐
func (s *Server) BuyVipPlan(_ context.Context, in *user.BuyVipPlanReq) (*user.BuyVipPlanResp, error) {
	plan, err := dao.ByVipPlan(in)
	if err != nil {
		return nil, fmt.Errorf("购买会员套餐失败：%s", err.Error())
	}
	return &user.BuyVipPlanResp{
		OrderId:   int64(plan.OrderId),
		StartTime: plan.StartTime.Format(time.DateTime),
		EndTime:   plan.EndTime.Format(time.DateTime),
	}, nil
}

// 用户查看会员套餐列表
func (s *Server) GetVipPlans(_ context.Context, in *user.GetVipPlansReq) (*user.GetVipPlansResp, error) {
	list, err := dao.GetVipPlansList(in)
	if err != nil {
		return nil, fmt.Errorf("获取会员套餐列表失败", err.Error())
	}
	return &user.GetVipPlansResp{
		Plans: list,
	}, nil
}

// 用户查看会员套餐详情
func (s *Server) GetUserVipInfo(_ context.Context, in *user.GetUserVipInfoReq) (*user.GetUserVipInfoResp, error) {
	detail, err := dao.GetVipPlansDetail(in)
	if err != nil {
		return nil, fmt.Errorf("获取会员套餐详情失败", err.Error())
	}
	return &user.GetUserVipInfoResp{
		PlanId:      int64(detail.PlanId),
		PlanName:    detail.PlanName,
		StartTime:   detail.StartTime.Format(time.DateTime),
		EndTime:     detail.EndTime.Format(time.DateTime),
		IsAvailable: int64(detail.IsActive),
	}, nil
}

// 购买虚拟商品
func (s *Server) BuyVirtualGoods(_ context.Context, in *user.BuyVirtualGoodsReq) (*user.BuyVirtualGoodsResp, error) {
	resp, err := dao.BuyVirtualGoods(in)
	if err != nil {
		return &user.BuyVirtualGoodsResp{
			Message: fmt.Sprintf("购买失败", err.Error()),
		}, nil
	}
	return resp, nil
}

// 获取用户钱包信息
func (s *Server) ALiPayNotify(_ context.Context, in *user.ALiPayNotifyReq) (*user.ALiPayNotifyResp, error) {
	_, err := dao.AliAPayNotify(in)
	if err != nil {
		return nil, fmt.Errorf("支付异步回调失败", err.Error())
	}
	return &user.ALiPayNotifyResp{}, nil
}

// 支付宝异步
func (s *Server) ALiPayReturn(_ context.Context, in *user.ALiPayReturnReq) (*user.ALiPayReturnResp, error) {
	payReturn, err := dao.AliPayReturn(in)
	if err != nil {
		return nil, fmt.Errorf("支付同步回调失败", err.Error())
	}
	return &user.ALiPayReturnResp{
		OrderSn:    payReturn.OrderSn,
		TotalPrice: float32(payReturn.TotalPrice),
		Message:    "支付成功",
	}, nil
}

// 支付宝同步
func (s *Server) GetUserWallet(_ context.Context, in *user.GetUserWalletReq) (*user.GetUserWalletResp, error) {
	wallet, err := dao.GetUserWallet(in)
	if err != nil {
		return nil, fmt.Errorf("获取用户钱包信息失败")
	}
	return &user.GetUserWalletResp{
		GoldCoins:     int64(wallet.GoldCoins),
		Diamonds:      int64(wallet.Diamonds),
		Points:        int64(wallet.Points),
		TotalRecharge: wallet.TotalRecharge,
		TotalSpent:    wallet.TotalSpent,
	}, nil
}

// 获取用户背包列表
func (s *Server) GetUserInventory(_ context.Context, in *user.GetUserInventoryReq) (*user.GetUserInventoryResp, error) {
	resp, err := dao.GetUserInventory(in)
	if err != nil {
		return &user.GetUserInventoryResp{
			List:      []*user.InventoryItem{},
			Total:     0,
			Page:      int32(in.Page),
			PageSize:  int32(in.PageSize),
			TotalPage: 0,
		}, fmt.Errorf("获取背包列表失败: %s", err.Error())
	}

	return resp, nil
}

// GetInterestTags 获取兴趣标签列表
// 功能：获取系统中所有可用的兴趣标签，用于用户选择
// 应用场景：用户注册或设置个人资料时需要选择感兴趣的标签
// 返回值：
//   - Tags: 兴趣标签列表，包含标签ID、名称、分类等信息
//   - Message: 查询结果信息
func (s *Server) GetInterestTags(_ context.Context, in *user.GetInterestTagsReq) (*user.GetInterestTagsResp, error) {
	// 查询所有启用的兴趣标签，按分类和排序字段排序
	var tagModel mobile.XqInterestTags
	tags, err := tagModel.List()
	if err != nil {
		return &user.GetInterestTagsResp{
			Tags:    nil,
			Message: "查询兴趣标签失败",
		}, err
	}

	// 转换为proto格式
	var protoTags []*user.InterestTag
	for _, tag := range tags {
		protoTags = append(protoTags, &user.InterestTag{
			Id:        tag.Id,
			Name:      tag.Name,
			Category:  tag.Category,
			SortOrder: tag.SortOrder,
		})
	}

	return &user.GetInterestTagsResp{
		Tags:    protoTags,
		Message: "获取成功",
	}, nil
}

// SaveUserInterests 保存用户兴趣选择
// 功能：保存用户选择的1-10个兴趣标签
// 逻辑：
//  1. 验证选择数量（1-10个）
//  2. 删除用户旧的选择
//  3. 保存新的兴趣选择
//
// 参数：
//   - in.UserId: 用户ID
//   - in.TagIds: 兴趣标签ID列表（1-10个）
//
// 返回值：
//   - Success: 是否成功
//   - Message: 操作结果信息
func (s *Server) SaveUserInterests(_ context.Context, in *user.SaveUserInterestsReq) (*user.SaveUserInterestsResp, error) {
	// 验证选择数量（1-10个）
	if len(in.TagIds) < 1 || len(in.TagIds) > 10 {
		return &user.SaveUserInterestsResp{
			Success: false,
			Message: "请选择1-10个兴趣标签",
		}, nil
	}

	// 先删除用户现有的兴趣选择
	var interestModel mobile.XqUserInterests
	err := interestModel.Delete(mobile.XqUserInterests{UserId: in.UserId})
	if err != nil {
		return &user.SaveUserInterestsResp{
			Success: false,
			Message: "清除旧兴趣选择失败",
		}, err
	}

	// 保存新的兴趣选择
	for _, tagId := range in.TagIds {
		userInterest := mobile.XqUserInterests{
			UserId: in.UserId,
			TagId:  tagId,
			Weight: 1.0, // 默认权重
		}
		err := userInterest.Create()
		if err != nil {
			return &user.SaveUserInterestsResp{
				Success: false,
				Message: "保存兴趣选择失败",
			}, err
		}
	}

	return &user.SaveUserInterestsResp{
		Success: true,
		Message: "兴趣选择保存成功",
	}, nil
}

// GetRecommendations 获取推荐用户列表
// 功能：基于用户兴趣和地理位置，为用户推荐合适的其他用户
// 算法逻辑：
//  1. 排除已滑动过的用户
//  2. 排除已匹配的用户
//  3. 基于兴趣相似度进行排序
//  4. 分页返回推荐结果
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.Page: 页码（从1开始）
//   - in.PageSize: 每页数量（默认10，最大50）
//
// 返回值：
//   - Users: 推荐用户列表
//   - Total: 总记录数
//   - Page/PageSize: 当前页码和每页数量
func (s *Server) GetRecommendations(_ context.Context, in *user.GetRecommendationsReq) (*user.GetRecommendationsResp, error) {

	page := in.Page
	if page <= 0 {
		page = 1
	}
	pageSize := in.PageSize
	if pageSize <= 0 {
		pageSize = 10
	}

	// 使用推荐服务获取推荐用户
	var recService dao.RecommendationService
	recommendations, err := recService.GetRecommendations(in.UserId, page, pageSize)
	if err != nil {
		return &user.GetRecommendationsResp{
			Users:    nil,
			Total:    0,
			Page:     page,
			PageSize: pageSize,
			Message:  "获取推荐用户失败",
		}, err
	}

	var protoUsers []*user.RecommendedUser
	for _, rec := range recommendations {
		protoUsers = append(protoUsers, &user.RecommendedUser{
			UserId:    rec.UserId,
			Nickname:  rec.Nickname,
			Age:       rec.Age,
			Avatar:    rec.Avatar,
			Bio:       rec.Bio,
			Interests: rec.Interests,
			Distance:  rec.Distance,
		})
	}

	return &user.GetRecommendationsResp{
		Users:    protoUsers,
		Total:    int32(len(protoUsers)),
		Page:     page,
		PageSize: pageSize,
		Message:  "获取推荐用户成功",
	}, nil
}

// SwipeUser 滑动操作（喜欢/无感）
// 功能：处理用户的滑动操作，记录滑动行为，如果双方互相喜欢则创建匹配
// 核心流程：
//  1. 验证参数和权限
//  2. 记录滑动行为到数据库
//  3. 如果是"喜欢"操作，检查对方是否也喜欢自己
//  4. 如果是双向喜欢，创建匹配关系并发送通知
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.TargetUserId: 目标用户ID
//   - in.Action: 滑动动作（0=无感，1=喜欢）
//
// 返回值：
//   - Success: 操作是否成功
//   - IsMatch: 是否匹配成功
//   - MatchId: 匹配记录ID（如果匹配成功）
func (s *Server) SwipeUser(_ context.Context, in *user.SwipeUserReq) (*user.SwipeUserResp, error) {
	// 验证参数
	if in.UserId <= 0 || in.TargetUserId <= 0 {
		return &user.SwipeUserResp{
			Success: false,
			IsMatch: false,
			Message: "无效的用户ID",
		}, nil
	}

	if in.UserId == in.TargetUserId {
		return &user.SwipeUserResp{
			Success: false,
			IsMatch: false,
			Message: "不能对自己进行滑动操作",
		}, nil
	}

	action := int8(in.Action)
	if action != 0 && action != 1 {
		return &user.SwipeUserResp{
			Success: false,
			IsMatch: false,
			Message: "无效的滑动动作",
		}, nil
	}

	// 使用滑动服务处理滑动操作
	var swipeService dao.SwipeService
	result, err := swipeService.ProcessSwipe(in.UserId, in.TargetUserId, action)
	if err != nil {
		return &user.SwipeUserResp{
			Success: false,
			IsMatch: false,
			Message: err.Error(),
		}, nil
	}

	return &user.SwipeUserResp{
		Success: result.Success,
		IsMatch: result.IsMatch,
		MatchId: result.MatchId,
		Message: result.Message,
	}, nil
}

// 获取匹配列表
// 功能：获取当前用户的所有匹配记录（聊天列表）
// 展示信息：
//   - 匹配用户的昵称、头像
//   - 最后一条消息内容
//   - 最后消息时间
//   - 匹配时间
//
// 参数：
//   - in.UserId: 用户ID
//   - in.Page: 页码
//   - in.PageSize: 每页数量
//
// 返回值：
//   - Matches: 匹配列表
//   - Total: 总记录数
func (s *Server) GetMatches(_ context.Context, in *user.GetMatchesReq) (*user.GetMatchesResp, error) {
	// 设置默认值
	page := in.Page
	if page <= 0 {
		page = 1
	}
	pageSize := in.PageSize
	if pageSize <= 0 {
		pageSize = 10
	}

	// 使用滑动服务获取匹配列表
	var swipeService dao.SwipeService
	matches, total, err := swipeService.GetUserMatches(in.UserId, page, pageSize)
	if err != nil {
		return &user.GetMatchesResp{
			Matches:  nil,
			Total:    0,
			Page:     page,
			PageSize: pageSize,
			Message:  "获取匹配列表失败",
		}, err
	}

	// 转换为proto格式
	var protoMatches []*user.Match
	for _, match := range matches {
		protoMatches = append(protoMatches, &user.Match{
			MatchId:         match.MatchId,
			UserId:          match.UserId,
			Nickname:        match.Nickname,
			Avatar:          match.Avatar,
			LastMessage:     match.LastMessage,
			LastMessageTime: match.LastMessageTime,
			MatchTime:       match.MatchTime,
		})
	}

	return &user.GetMatchesResp{
		Matches:  protoMatches,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
		Message:  "获取匹配列表成功",
	}, nil
}

//	获取匹配详情
//
// 功能：获取特定匹配的详细信息
// 包含信息：
//   - 匹配用户的详细信息（昵称、头像、简介等）
//   - 用户兴趣标签
//   - 匹配时间
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.MatchId: 匹配记录ID
func (s *Server) GetMatchDetail(_ context.Context, in *user.GetMatchDetailReq) (*user.GetMatchDetailResp, error) {
	// 使用滑动服务获取匹配详情
	var swipeService dao.SwipeService
	detail, err := swipeService.GetMatchDetail(in.UserId, in.MatchId)
	if err != nil {
		return &user.GetMatchDetailResp{
			MatchId:   0,
			UserId:    0,
			Nickname:  "",
			Avatar:    "",
			Bio:       "",
			Interests: nil,
			MatchTime: 0,
			Message:   err.Error(),
		}, nil
	}

	return &user.GetMatchDetailResp{
		MatchId:   detail.MatchId,
		UserId:    detail.UserId,
		Nickname:  detail.Nickname,
		Avatar:    detail.Avatar,
		Bio:       detail.Bio,
		Interests: detail.Interests,
		MatchTime: detail.MatchTime,
		Message:   "获取匹配详情成功",
	}, nil
}

// SendMessage 发送聊天消息
// 功能：在匹配关系中发送消息
// 处理流程：
//  1. 验证匹配关系
//  2. 保存消息到数据库
//  3. 通过WebSocket实时推送给接收方
//  4. 发送推送通知给离线用户
//
// 参数：
//   - in.UserId: 发送者ID
//   - in.MatchId: 匹配关系ID
//   - in.Content: 消息内容
//   - in.MsgType: 消息类型（1=文本，2=图片，3=语音）
//
// 返回值：
//   - MessageId: 消息ID
//   - Success: 是否成功发送
func (s *Server) SendMessage(_ context.Context, in *user.SendMessageReq) (*user.SendMessageResp, error) {
	// 验证参数
	if in.UserId <= 0 || in.MatchId <= 0 {
		return &user.SendMessageResp{
			MessageId: 0,
			Success:   false,
			Message:   "参数错误",
		}, nil
	}

	if in.Content == "" {
		return &user.SendMessageResp{
			MessageId: 0,
			Success:   false,
			Message:   "消息内容不能为空",
		}, nil
	}

	// 使用聊天服务发送消息
	var chatService dao.ChatService
	messageInfo, err := chatService.SendMessage(in.UserId, in.MatchId, in.Content, int8(in.MsgType))
	if err != nil {
		return &user.SendMessageResp{
			MessageId: 0,
			Success:   false,
			Message:   err.Error(),
		}, nil
	}

	return &user.SendMessageResp{
		MessageId: messageInfo.Id,
		Success:   true,
		Message:   "消息发送成功",
	}, nil
}

// GetChatMessages 获取聊天消息列表
// 功能：获取指定匹配关系的聊天消息历史
// 自动处理：
//   - 按时间倒序排列（最新的在前）
//   - 自动标记消息为已读
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.MatchId: 匹配关系ID
//   - in.Page: 页码
//   - in.PageSize: 每页数量（默认20）
func (s *Server) GetChatMessages(_ context.Context, in *user.GetChatMessagesReq) (*user.GetChatMessagesResp, error) {
	// 设置默认值
	page := in.Page
	pageSize := in.PageSize
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 {
		pageSize = 20
	}

	// 使用聊天服务获取消息列表
	var chatService dao.ChatService
	messages, total, err := chatService.GetChatMessages(in.UserId, in.MatchId, page, pageSize)
	if err != nil {
		return &user.GetChatMessagesResp{
			Messages: nil,
			Total:    0,
			Page:     page,
			PageSize: pageSize,
			Message:  err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoMessages []*user.ChatMessage
	for _, msg := range messages {
		protoMessages = append(protoMessages, &user.ChatMessage{
			Id:        msg.Id,
			MatchId:   msg.MatchId,
			SenderId:  msg.SenderId,
			Content:   msg.Content,
			MsgType:   int32(msg.MsgType),
			IsRead:    int32(msg.IsRead),
			CreatedAt: msg.CreatedAt,
		})
	}

	return &user.GetChatMessagesResp{
		Messages: protoMessages,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
		Message:  "获取消息列表成功",
	}, nil
}

// MarkMessagesAsRead 标记消息为已读
// 功能：将某个匹配关系的所有未读消息标记为已读
// 应用场景：用户打开聊天界面时自动调用
// 参数：
//   - in.UserId: 用户ID
//   - in.MatchId: 匹配关系ID
func (s *Server) MarkMessagesAsRead(_ context.Context, in *user.MarkMessagesAsReadReq) (*user.MarkMessagesAsReadResp, error) {
	// 使用聊天服务标记消息为已读
	var chatService dao.ChatService
	err := chatService.MarkMessagesAsRead(in.UserId, in.MatchId)
	if err != nil {
		return &user.MarkMessagesAsReadResp{
			Success: false,
			Message: err.Error(),
		}, nil
	}

	return &user.MarkMessagesAsReadResp{
		Success: true,
		Message: "消息已标记为已读",
	}, nil
}

// GetUnreadMessageCount 获取未读消息数量
// 功能：统计用户在所有匹配关系中的未读消息总数
// 应用场景：在界面右上角显示红点通知
func (s *Server) GetUnreadMessageCount(_ context.Context, in *user.GetUnreadMessageCountReq) (*user.GetUnreadMessageCountResp, error) {
	// 使用聊天服务获取未读消息数量
	var chatService dao.ChatService
	count, err := chatService.GetUnreadMessageCount(in.UserId)
	if err != nil {
		return &user.GetUnreadMessageCountResp{
			Count:   0,
			Message: err.Error(),
		}, nil
	}

	return &user.GetUnreadMessageCountResp{
		Count:   count,
		Message: "获取未读消息数量成功",
	}, nil
}

// GetNotifications 获取用户通知列表
// 功能：获取用户的所有系统通知
// 通知类型：
//   - 匹配通知：新匹配成功
//   - 消息通知：收到新消息
//
// 参数：
//   - in.UserId: 用户ID
//   - in.Page: 页码
//   - in.PageSize: 每页数量
func (s *Server) GetNotifications(_ context.Context, in *user.GetNotificationsReq) (*user.GetNotificationsResp, error) {
	// 设置默认值
	page := in.Page
	pageSize := in.PageSize
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 {
		pageSize = 10
	}

	// 使用通知服务获取通知列表
	var notificationService dao.NotificationService
	notifications, total, err := notificationService.GetUserNotifications(in.UserId, page, pageSize)
	if err != nil {
		return &user.GetNotificationsResp{
			Notifications: nil,
			Total:         0,
			Page:          page,
			PageSize:      pageSize,
			Message:       err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoNotifications []*user.Notification
	for _, notification := range notifications {
		protoNotifications = append(protoNotifications, &user.Notification{
			Id:        notification.Id,
			Type:      int32(notification.Type),
			Title:     notification.Title,
			Content:   notification.Content,
			RelatedId: notification.RelatedId,
			IsRead:    int32(notification.IsRead),
			CreatedAt: notification.CreatedAt,
		})
	}

	return &user.GetNotificationsResp{
		Notifications: protoNotifications,
		Total:         total,
		Page:          page,
		PageSize:      pageSize,
		Message:       "获取通知列表成功",
	}, nil
}

// MarkNotificationAsRead 标记通知为已读
// 功能：将特定通知标记为已读状态
// 参数：
//   - in.UserId: 用户ID
//   - in.NotificationId: 通知ID
func (s *Server) MarkNotificationAsRead(_ context.Context, in *user.MarkNotificationAsReadReq) (*user.MarkNotificationAsReadResp, error) {
	// 使用通知服务标记通知为已读
	var notificationService dao.NotificationService
	err := notificationService.MarkNotificationAsRead(in.UserId, in.NotificationId)
	if err != nil {
		return &user.MarkNotificationAsReadResp{
			Success: false,
			Message: err.Error(),
		}, nil
	}

	return &user.MarkNotificationAsReadResp{
		Success: true,
		Message: "通知已标记为已读",
	}, nil
}

// GetSmartRecommendations 获取智能推荐用户
// 功能：基于兴趣匹配算法，智能推荐相似用户
// 算法特点：
//   - 计算用户间的兴趣相似度
//   - 分析共同兴趣标签
//   - 综合匹配分数
//   - 显示地理位置信息
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.Limit: 推荐数量（默认20）
//
// 返回值：
//   - Recommendations: 推荐用户列表（包含相似度、共同标签、距离等）
//   - Total: 推荐总数
func (s *Server) GetSmartRecommendations(_ context.Context, in *user.GetSmartRecommendationsReq) (*user.GetSmartRecommendationsResp, error) {
	var interestMatchingService dao.InterestMatchingService

	// 设置默认值
	limit := int(in.Limit)
	if limit <= 0 {
		limit = 20
	}

	// 获取智能推荐
	recommendations, err := interestMatchingService.GetSmartRecommendations(in.UserId, limit)
	if err != nil {
		return &user.GetSmartRecommendationsResp{
			Recommendations: nil,
			Total:           0,
			Message:         "获取智能推荐失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoRecommendations []*user.SmartRecommendationInfo
	for _, rec := range recommendations {
		protoRecommendations = append(protoRecommendations, &user.SmartRecommendationInfo{
			UserId:      rec.UserId,
			Nickname:    rec.Nickname,
			Avatar:      rec.Avatar,
			Age:         int32(rec.Age),
			Gender:      int32(rec.Gender),
			Bio:         rec.Bio,
			Similarity:  rec.Similarity,
			CommonTags:  rec.CommonTags,
			CommonCount: int32(rec.CommonCount),
			MatchScore:  rec.MatchScore,
			DistanceKm:  rec.DistanceKm,
			City:        rec.City,
		})
	}

	return &user.GetSmartRecommendationsResp{
		Recommendations: protoRecommendations,
		Total:           int32(len(protoRecommendations)),
		Message:         "获取智能推荐成功",
	}, nil
}

// GetSoulQuestions 获取灵魂问答题目
// 功能：获取灵魂匹配的问答题目，用于深度了解用户
// 题目特点：
//   - 涵盖不同分类（性格、价值观、生活方式等）
//   - 单选或多选题
//   - 每道题有权重（重要程度）
//
// 参数：
//   - in.UserId: 用户ID
//   - in.Category: 题目分类
//   - in.Limit: 题目数量
func (s *Server) GetSoulQuestions(_ context.Context, in *user.GetSoulQuestionsReq) (*user.GetSoulQuestionsResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 设置默认值
	limit := int(in.Limit)
	if limit <= 0 {
		limit = 20
	}

	// 获取题目
	questions, err := soulMatchingService.GetSoulQuestions(in.UserId, in.Category, int32(limit))
	if err != nil {
		return &user.GetSoulQuestionsResp{
			Questions: nil,
			Total:     0,
			Message:   "获取题目失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoQuestions []*user.SoulQuestion
	for _, question := range questions {
		var options []string
		if question.Options != "" {
			json.Unmarshal([]byte(question.Options), &options)
		}

		protoQuestions = append(protoQuestions, &user.SoulQuestion{
			Id:           question.Id,
			Question:     question.Question,
			Category:     question.Category,
			QuestionType: int32(question.QuestionType),
			Options:      options,
			Weight:       question.Weight,
		})
	}

	return &user.GetSoulQuestionsResp{
		Questions: protoQuestions,
		Total:     int32(len(protoQuestions)),
		Message:   "获取题目成功",
	}, nil
}

// SubmitSoulAnswer 提交灵魂问答答案
// 功能：提交用户对题目的答案
// 处理流程：
//  1. 检查是否已答过该题
//  2. 保存答案到数据库
//  3. 更新用户灵魂档案完成度
//
// 参数：
//   - in.UserId: 用户ID
//   - in.QuestionId: 题目ID
//   - in.Answers: 答案列表（支持多选）
//   - in.AnswerScore: 答案分数
func (s *Server) SubmitSoulAnswer(_ context.Context, in *user.SubmitSoulAnswerReq) (*user.SubmitSoulAnswerResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 提交答案
	err := soulMatchingService.SubmitSoulAnswer(in.UserId, in.QuestionId, in.Answers, in.AnswerScore)
	if err != nil {
		return &user.SubmitSoulAnswerResp{
			Success: false,
			Message: "提交答案失败: " + err.Error(),
		}, nil
	}

	return &user.SubmitSoulAnswerResp{
		Success: true,
		Message: "提交答案成功",
	}, nil
}

// GetSoulMatches 获取灵魂匹配结果
// 功能：获取基于灵魂问答的匹配结果
// 匹配逻辑：
//   - 计算用户间的答案相似度
//   - 分析共同答案
//   - 生成匹配分数和理由
//
// 参数：
//   - in.UserId: 用户ID
//   - in.Page: 页码
//   - in.PageSize: 每页数量
//
// 返回值：
//   - Matches: 灵魂匹配用户列表（包含契合度分数）
func (s *Server) GetSoulMatches(_ context.Context, in *user.GetSoulMatchesReq) (*user.GetSoulMatchesResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 设置默认值
	page := in.Page
	if page <= 0 {
		page = 1
	}
	pageSize := in.PageSize
	if pageSize <= 0 {
		pageSize = 20
	}

	// 获取匹配结果
	matches, total, err := soulMatchingService.GetSoulMatches(in.UserId, page, pageSize)
	if err != nil {
		return &user.GetSoulMatchesResp{
			Matches:  nil,
			Total:    0,
			Page:     page,
			PageSize: pageSize,
			Message:  "获取匹配结果失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoMatches []*user.SoulMatchInfo
	for _, match := range matches {
		protoMatches = append(protoMatches, &user.SoulMatchInfo{
			UserId:             match.UserID,
			Nickname:           match.Nickname,
			Avatar:             match.Avatar,
			Age:                match.Age,
			Gender:             match.Gender,
			Bio:                match.Bio,
			CompatibilityScore: match.CompatibilityScore,
			CreatedAt:          match.CreatedAt,
		})
	}

	return &user.GetSoulMatchesResp{
		Matches:  protoMatches,
		Total:    total,
		Page:     page,
		PageSize: pageSize,
		Message:  "获取匹配结果成功",
	}, nil
}

// GetSoulMatchDetail 获取灵魂匹配详情
// 功能：获取与特定用户的灵魂匹配详情
// 详细信息：
//   - 契合度分数
//   - 共同答案列表
//   - 匹配理由
//   - 人格类型
//   - 个性描述
//
// 参数：
//   - in.UserId: 当前用户ID
//   - in.TargetUserId: 目标用户ID
func (s *Server) GetSoulMatchDetail(_ context.Context, in *user.GetSoulMatchDetailReq) (*user.GetSoulMatchDetailResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 获取匹配详情
	detail, err := soulMatchingService.GetSoulMatchDetail(in.UserId, in.TargetUserId)
	if err != nil {
		return &user.GetSoulMatchDetailResp{
			MatchDetail: nil,
			Message:     "获取匹配详情失败: " + err.Error(),
		}, nil
	}

	// 转换共同答案为proto格式
	var protoCommonAnswers []*user.CommonAnswer
	for _, answer := range detail.CommonAnswers {
		protoCommonAnswers = append(protoCommonAnswers, &user.CommonAnswer{
			QuestionId:    answer.QuestionID,
			Question:      answer.Question,
			CommonAnswers: answer.CommonAnswers,
		})
	}

	// 转换为proto格式
	protoDetail := &user.SoulMatchDetail{
		UserId:             detail.UserID,
		Nickname:           detail.Nickname,
		Avatar:             detail.Avatar,
		Age:                detail.Age,
		Gender:             detail.Gender,
		Bio:                detail.Bio,
		CompatibilityScore: detail.CompatibilityScore,
		CommonAnswers:      protoCommonAnswers,
		MatchReasons:       detail.MatchReasons,
		PersonalityType:    detail.PersonalityType,
		CreatedAt:          detail.CreatedAt,
	}

	return &user.GetSoulMatchDetailResp{
		MatchDetail: protoDetail,
		Message:     "获取匹配详情成功",
	}, nil
}

// GetUserSoulProfile 获取用户灵魂档案
// 功能：获取当前用户的灵魂档案信息
// 档案信息：
//   - 完成度（已答题数/总题数）
//   - 人格类型
//   - 关系风格
//   - 最后答题时间
func (s *Server) GetUserSoulProfile(_ context.Context, in *user.GetUserSoulProfileReq) (*user.GetUserSoulProfileResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 获取灵魂档案
	profile, err := soulMatchingService.GetUserSoulProfile(in.UserId)
	if err != nil {
		return &user.GetUserSoulProfileResp{
			Profile: nil,
			Message: "获取灵魂档案失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	protoProfile := &user.UserSoulProfile{
		UserId:            profile.UserId,
		PersonalityType:   profile.PersonalityType,
		RelationshipStyle: profile.RelationshipStyle,
		CompletionRate:    profile.CompletionRate,
		LastAnsweredAt:    profile.LastAnsweredAt.Unix(),
	}

	return &user.GetUserSoulProfileResp{
		Profile: protoProfile,
		Message: "获取灵魂档案成功",
	}, nil
}

// CalculateSoulCompatibility 计算灵魂契合度
// 功能：计算两个用户之间的灵魂契合度
// 计算维度：
//   - 答案一致性（共同答案数量）
//   - 答案深度（重要题目的答案）
//   - 总体契合度分数
//
// 参数：
//   - in.UserId1: 用户1 ID
//   - in.UserId2: 用户2 ID
//
// 返回值：
//   - CompatibilityScore: 契合度分数（0-100）
//   - CommonAnswers: 共同答案列表
//   - MatchReasons: 匹配原因
func (s *Server) CalculateSoulCompatibility(_ context.Context, in *user.CalculateSoulCompatibilityReq) (*user.CalculateSoulCompatibilityResp, error) {
	soulMatchingService := dao.NewSoulMatchingService()

	// 计算契合度
	result, err := soulMatchingService.CalculateSoulCompatibility(in.UserId1, in.UserId2)
	if err != nil {
		return &user.CalculateSoulCompatibilityResp{
			Result:  nil,
			Message: "计算契合度失败: " + err.Error(),
		}, nil
	}

	// 转换共同答案为proto格式
	var protoCommonAnswers []*user.CommonAnswer
	for _, answer := range result.CommonAnswers {
		protoCommonAnswers = append(protoCommonAnswers, &user.CommonAnswer{
			QuestionId:    answer.QuestionID,
			Question:      answer.Question,
			CommonAnswers: answer.CommonAnswers,
		})
	}

	// 转换为proto格式
	protoResult := &user.SoulCompatibilityResult{
		UserId1:            result.UserID1,
		UserId2:            result.UserID2,
		CompatibilityScore: result.CompatibilityScore,
		CommonAnswers:      protoCommonAnswers,
		MatchReasons:       result.MatchReasons,
		CommonCount:        int32(result.CommonCount),
		TotalQuestions:     int32(result.TotalQuestions),
	}

	return &user.CalculateSoulCompatibilityResp{
		Result:  protoResult,
		Message: "计算契合度成功",
	}, nil
}

//
//附   近   的   人   查   询   功   能

// UpdateLocation 更新用户位置
// 功能：更新用户的实时地理位置信息
// 应用场景：
//   - 用户打开APP时自动更新位置
//   - 用于"附近的人"功能
//   - 基于地理位置进行用户推荐
//
// 参数：
//   - in.UserId: 用户ID
//   - in.Latitude: 纬度（-90到90）
//   - in.Longitude: 经度（-180到180）
//   - in.City: 城市名称
func (s *Server) UpdateLocation(_ context.Context, in *user.UpdateLocationReq) (*user.UpdateLocationResp, error) {
	// 参数验证
	if in.UserId <= 0 {
		return &user.UpdateLocationResp{
			Success: false,
			Message: "用户ID无效",
		}, nil
	}

	// 坐标范围验证
	if in.Latitude < -90 || in.Latitude > 90 || in.Longitude < -180 || in.Longitude > 180 {
		return &user.UpdateLocationResp{
			Success: false,
			Message: "坐标范围无效",
		}, nil
	}

	// 调用LBS服务更新位置
	lbsService := dao.NewLBSService()
	err := lbsService.UpdateLocation(in.UserId, in.Latitude, in.Longitude, in.City, "")
	if err != nil {
		return &user.UpdateLocationResp{
			Success: false,
			Message: "更新位置失败: " + err.Error(),
		}, nil
	}

	return &user.UpdateLocationResp{
		Success: true,
		Message: "位置更新成功",
	}, nil
}

// GetNearbyUsers 获取附近的人
// 功能：基于用户位置，查找附近的用户
// 算法：
//   - 使用Haversine公式计算精确距离
//   - 按距离排序
//   - 返回用户基本信息+距离
//
// Haversine 公式是通过两点的经纬度，计算地球表面两点间最短距离（大圆距离）的经典数学公式
// 实现的 LBS（Location-Based Service，基于位置的服务）功能，核心作用是根据当前用户的经纬度和搜索半径，获取附近的其他用户信息。
// 参数：
//   - in.UserId: 当前用户ID
//   - in.Latitude: 纬度
//   - in.Longitude: 经度
//   - in.Radius: 搜索半径（公里，默认10）
//
// 返回值：
//   - Users: 附近用户列表（包含距离、城市等信息）
func (s *Server) GetNearbyUsers(_ context.Context, in *user.GetNearbyUsersReq) (*user.GetNearbyUsersResp, error) {
	// 参数验证
	if in.UserId <= 0 {
		return &user.GetNearbyUsersResp{
			Message: "用户ID无效",
		}, nil
	}

	// 坐标范围验证
	if in.Latitude < -90 || in.Latitude > 90 || in.Longitude < -180 || in.Longitude > 180 {
		return &user.GetNearbyUsersResp{
			Message: "坐标范围无效",
		}, nil
	}

	// 设置默认半径（公里）
	radius := in.Radius
	if radius <= 0 {
		radius = 10 // 默认10公里
	}

	// 调用LBS服务获取附近用户
	lbsService := dao.NewLBSService()
	users, err := lbsService.GetNearbyUsers(in.UserId, in.Latitude, in.Longitude, radius)
	if err != nil {
		return &user.GetNearbyUsersResp{
			Message: "获取附近用户失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	var protoUsers []*user.NearbyUserInfo
	for _, u := range users {
		protoUsers = append(protoUsers, &user.NearbyUserInfo{
			UserId:     u.UserId,
			Nickname:   u.Nickname,
			Avatar:     u.Avatar,
			Age:        u.Age,
			Gender:     u.Gender,
			DistanceKm: u.DistanceKm,
			City:       u.City,
		})
	}

	return &user.GetNearbyUsersResp{
		Users:   protoUsers,
		Message: "获取附近用户成功",
	}, nil
}

// GetUserLocation 获取用户位置
// 功能：获取指定用户的最新位置信息
// 应用场景：
//   - 查看自己的位置信息
//   - 获取好友位置（需要授权）
func (s *Server) GetUserLocation(_ context.Context, in *user.GetUserLocationReq) (*user.GetUserLocationResp, error) {
	// 参数验证
	if in.UserId <= 0 {
		return &user.GetUserLocationResp{
			Message: "用户ID无效",
		}, nil
	}

	// 调用LBS服务获取用户位置
	lbsService := dao.NewLBSService()
	location, err := lbsService.GetUserLocation(in.UserId)
	if err != nil {
		return &user.GetUserLocationResp{
			Message: "获取用户位置失败: " + err.Error(),
		}, nil
	}

	// 转换为proto格式
	protoLocation := &user.UserLocationInfo{
		UserId:    location.UserId,
		Latitude:  location.Latitude,
		Longitude: location.Longitude,
		City:      location.City,
		UpdatedAt: location.UpdatedAt.Unix(),
	}

	return &user.GetUserLocationResp{
		Location: protoLocation,
		Message:  "获取用户位置成功",
	}, nil
}

// 发表好友动态
func (s *Server) PostFriendActivity(_ context.Context, in *user.PostFriendActivityReq) (*user.PostFriendActivityResp, error) {
	var fas dao.FriendActivityService
	id, err := fas.PostActivity(in.UserId, in.Content, in.Images)
	if err != nil {
		return &user.PostFriendActivityResp{Success: false, ActivityId: 0, Message: err.Error()}, nil
	}
	return &user.PostFriendActivityResp{Success: true, ActivityId: id, Message: "发布成功"}, nil
}

// 获取好友动态
func (s *Server) GetFriendActivities(_ context.Context, in *user.GetFriendActivitiesReq) (*user.GetFriendActivitiesResp, error) {
	var fas dao.FriendActivityService
	list, total, err := fas.GetFeed(in.UserId, in.Page, in.PageSize)
	if err != nil {
		return &user.GetFriendActivitiesResp{Activities: nil, Total: 0, Page: in.Page, PageSize: in.PageSize, Message: err.Error()}, nil
	}
	activities := make([]*user.FriendActivityItem, 0, len(list))
	for _, a := range list {
		var imgs []string
		if a.Images != "" {
			_ = json.Unmarshal([]byte(a.Images), &imgs)
		}
		activities = append(activities, &user.FriendActivityItem{
			Id:        a.Id,
			UserId:    a.UserId,
			Content:   a.Content,
			Images:    imgs,
			CreatedAt: a.CreatedAt.Unix(),
		})
	}
	return &user.GetFriendActivitiesResp{Activities: activities, Total: total, Page: in.Page, PageSize: in.PageSize, Message: "获取成功"}, nil
}

// ========== 好友系统 ==========

func (s *Server) AddFriend(_ context.Context, in *user.AddFriendReq) (*user.AddFriendResp, error) {
	var fs dao.FriendService
	if err := fs.AddFriend(in.UserId, in.TargetUserId, in.GroupId, in.Remark); err != nil {
		return &user.AddFriendResp{Success: false, Message: err.Error()}, nil
	}
	return &user.AddFriendResp{Success: true, Message: "添加好友成功"}, nil
}

func (s *Server) RemoveFriend(_ context.Context, in *user.RemoveFriendReq) (*user.RemoveFriendResp, error) {
	var fs dao.FriendService
	if err := fs.RemoveFriend(in.UserId, in.TargetUserId); err != nil {
		return &user.RemoveFriendResp{Success: false, Message: err.Error()}, nil
	}
	return &user.RemoveFriendResp{Success: true, Message: "删除好友成功"}, nil
}

func (s *Server) GetFriends(_ context.Context, in *user.GetFriendsReq) (*user.GetFriendsResp, error) {
	// 列出分组
	var gm mobile.XqFriendGroups
	groups, err := gm.ListByUser(in.UserId)
	if err != nil {
		return &user.GetFriendsResp{Groups: nil, Message: err.Error()}, nil
	}
	// 构建分组及好友
	var respGroups []*user.FriendGroupInfo
	for _, g := range groups {
		var uf mobile.XqUserFriends
		friends, err := uf.ListByGroup(in.UserId, g.Id)
		if err != nil {
			continue
		}
		var protoFriends []*user.FriendInfo
		for _, f := range friends {
			// 取好友基本资料
			var profile mobile.XqUserProfiles
			p, _ := profile.GetByUserId(f.FriendId)
			protoFriends = append(protoFriends, &user.FriendInfo{
				UserId:   f.FriendId,
				Nickname: p.Nickname,
				Avatar:   p.Avatar,
				Remark:   f.Remark,
				AddedAt:  f.CreatedAt.Unix(),
			})
		}
		respGroups = append(respGroups, &user.FriendGroupInfo{
			GroupId:   g.Id,
			GroupName: g.GroupName,
			SortOrder: g.SortOrder,
			Friends:   protoFriends,
		})
	}
	return &user.GetFriendsResp{Groups: respGroups, Message: "获取好友列表成功"}, nil
}

func (s *Server) CreateFriendGroup(_ context.Context, in *user.CreateFriendGroupReq) (*user.CreateFriendGroupResp, error) {
	var fs dao.FriendService
	gid, err := fs.CreateGroup(in.UserId, in.GroupName)
	if err != nil {
		return &user.CreateFriendGroupResp{Success: false, GroupId: 0, Message: err.Error()}, nil
	}
	return &user.CreateFriendGroupResp{Success: true, GroupId: gid, Message: "创建分组成功"}, nil
}

func (s *Server) RenameFriendGroup(_ context.Context, in *user.RenameFriendGroupReq) (*user.RenameFriendGroupResp, error) {
	var fs dao.FriendService
	if err := fs.RenameGroup(in.UserId, in.GroupId, in.GroupName); err != nil {
		return &user.RenameFriendGroupResp{Success: false, Message: err.Error()}, nil
	}
	return &user.RenameFriendGroupResp{Success: true, Message: "重命名成功"}, nil
}

func (s *Server) DeleteFriendGroup(_ context.Context, in *user.DeleteFriendGroupReq) (*user.DeleteFriendGroupResp, error) {
	var fs dao.FriendService
	if err := fs.DeleteGroup(in.UserId, in.GroupId); err != nil {
		return &user.DeleteFriendGroupResp{Success: false, Message: err.Error()}, nil
	}
	return &user.DeleteFriendGroupResp{Success: true, Message: "删除分组成功"}, nil
}

func (s *Server) MoveFriendToGroup(_ context.Context, in *user.MoveFriendToGroupReq) (*user.MoveFriendToGroupResp, error) {
	var fs dao.FriendService
	if err := fs.MoveFriendToGroup(in.UserId, in.TargetUserId, in.ToGroupId); err != nil {
		return &user.MoveFriendToGroupResp{Success: false, Message: err.Error()}, nil
	}
	return &user.MoveFriendToGroupResp{Success: true, Message: "移动成功"}, nil
}
